/*
	message_handling.h

	Contains function headers and kernel tables for the IPC message handling functionality

	Author: Aidan Goddard 21/8/13
*/

#ifndef MESSAGE_HANDLING_H_INCLUDED
#define MESSAGE_HANDLING_H_INCLUDED

#include"kernel_tables.h"

typedef struct MSG MSG;
struct __attribute__((__packed__,aligned(256))) MSG
{
	volatile uint64_t data[32];
};

typedef struct MSG_BUFFER MSG_BUFFER;
struct __attribute__((__packed__,aligned(32*1024))) MSG_BUFFER
{
	MSG server_queue[64];
	MSG client_queue[64];
};

typedef struct MSG_CONTROL MSG_CONTROL;
struct __attribute__((__packed__,aligned(1024))) MSG_CONTROL
{
	// buffer lock
	SCH_CLS lock;

	// IDs
	volatile uint64_t server_ID;
	volatile uint64_t client_ID;
	volatile uint64_t channel_ID;

	// server destination side queue controls
	volatile uint32_t server_message_count;
	volatile uint32_t server_queue_start;
	volatile uint32_t server_queue_last;			// not used?

	// client destination side queue controls
	volatile uint32_t client_message_count;
	volatile uint32_t client_queue_start;
	volatile uint32_t client_queue_last;			// not used?

	// syncronisation controls
	volatile uint64_t client_read_waiting_TID;
	volatile uint64_t client_write_sync_waiting_TID;
	volatile uint64_t server_read_waiting_TID;
	volatile uint64_t server_write_sync_waiting_TID;

};

// main control table
typedef struct MSG_CONTROL_MAIN MSG_CONTROL_MAIN;
struct __attribute__((__packed__)) MSG_CONTROL_MAIN
{
	// individual buffer control areas
	MSG_CONTROL buffer_controls[512];

	// buffer allocation stack
	SCH_CLS stack_lock;
	volatile uint32_t buffer_stack[512];
	volatile uint32_t buffer_stack_index;
};

// some global pointers
static MSG_CONTROL_MAIN *msg_control = (MSG_CONTROL_MAIN*)(KOFFSET + 0x1500000);
static MSG_BUFFER *msg_buffers = (MSG_BUFFER*)(KOFFSET + 0x1600000);

// the message passing system identifier type
typedef uint64_t MSG_CHANNEL;

// setup function
void SetupMessageHandler(void);

// allocation and binding functions
MSG_CHANNEL	AllocateChannel(char *magic_string, uint32_t magic_int);
uint32_t	DeallocateChannel(MSG_CHANNEL channel);
MSG_CHANNEL FindChannel(char *magic_string, uint32_t magic_int);
uint32_t	ClientBindChannel(uint64_t PID, MSG_CHANNEL channel);

// message read functions
uint32_t	ServerRead(MSG_CHANNEL channel, uint8_t *buffer);
uint32_t	ServerPeek(MSG_CHANNEL channel);
uint32_t	ClientRead(MSG_CHANNEL channel, uint8_t *buffer, uint64_t PID);
uint32_t	ClientPeek(MSG_CHANNEL channel, uint64_t PID);

// message send functions
uint32_t	ServerSendSync(MSG_CHANNEL channel, uint8_t *buffer);
uint32_t 	ServerSendAsync(MSG_CHANNEL channel, uint8_t *buffer);
uint32_t 	ClientSendSync(MSG_CHANNEL channel, uint8_t *buffer, uint64_t PID);
uint32_t 	ClientSendAsync(MSG_CHANNEL channel, uint8_t *buffer, uint64_t PID);

// functions for querying the number of pending messages in a buffer (can be called by anyone as long as the channel is correct)
uint32_t	GetClientPendingMessages(MSG_CHANNEL channel);
uint32_t	GetServerPendingMessages(MSG_CHANNEL channel);

// function to deallocate all queues associated with the given server PID
void	DeallocateForServerPID(uint64_t PID);





#endif
